home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
ada
/
gwuada_9.zip
/
PROC.C
< prev
next >
Wrap
C/C++ Source or Header
|
1993-07-27
|
38KB
|
1,163 lines
/*
* Copyright (C) 1985-1992 New York University
*
* This file is part of the Ada/Ed-C system. See the Ada/Ed README file for
* warranty (none) and distribution info and also the GNU General Public
* License for more details.
*/
#define GEN
#include "hdr.h"
#include "libhdr.h"
#include "vars.h"
#include "segment.h"
#include "gvars.h"
#include "ops.h"
#include "type.h"
#include "axqrp.h"
#include "namp.h"
#include "maincasp.h"
#include "exprp.h"
#include "dbxp.h"
#include "miscp.h"
#include "libp.h"
#include "statp.h"
#include "setp.h"
#include "genp.h"
#include "segmentp.h"
#include "gmiscp.h"
#include "smiscp.h"
#include "gutilp.h"
#include "procp.h"
extern Segment CODE_SEGMENT, DATA_SEGMENT, DATA_SEGMENT_MAIN;
void gen_subprogram_spec(Node proc_node) /*;gen_subprogram_spec*/
{
/* subprogram spec.
* Just reserve a code slot, and GENERATE the procedure object.
* If the spec occurs elsewhere than immediately in the declarative part
* of a compilation unit, it may need a relay set, but we don't know it
* yet. So, we must prepare for a dynamically elaborated procedure.
*/
int save_current_code_segment;
Symbol proc_name;
Tuple predef_tuple;
#ifdef TRACE
if (debug_flag)
gen_trace_node("GEN_SUBPROGRAM_SPEC", proc_node);
#endif
proc_name = N_UNQ(proc_node);
/*tag = NATURE(proc_name);*/
predef_tuple = (Tuple) MISC(proc_name);
if (predef_tuple != (Tuple)0) { /*predef */
}
else {
save_current_code_segment = CURRENT_CODE_SEGMENT;
CURRENT_CODE_SEGMENT = select_entry(SELECT_CODE, proc_name, SLOTS_CODE);
#ifdef TRACE
if (list_code) {
to_gen(" ");
to_gen_unam("--------------------------------------",
ORIG_NAME(proc_name), "--------------");
to_gen_int(" code slot # ", CURRENT_CODE_SEGMENT);
to_gen(" ");
}
#endif
if (CURRENT_LEVEL == 1) { /* No relay set needed */
next_global_reference_r(proc_name, CURRENT_CODE_SEGMENT, 0);
}
else {
next_local_reference(proc_name);
}
/* Empty segment */
CODE_SEGMENT_MAP = segment_map_put(CODE_SEGMENT_MAP,
CURRENT_CODE_SEGMENT, segment_new(SEGMENT_KIND_CODE, 0));
SPECS_DECLARED += 1;
if (!tup_mem((char *) proc_name, SUBPROG_SPECS)) {
SUBPROG_SPECS = tup_with(SUBPROG_SPECS, (char *) proc_name);
}
#ifdef MACHINE_CODE
if (list_code) {
to_gen_unam("-------- end ", ORIG_NAME(proc_name),
" -----------");
}
#endif
CURRENT_CODE_SEGMENT = save_current_code_segment;
if (CURRENT_LEVEL != 1) {
gen(I_END); /* Purge peep-hole */
subprog_patch_put(proc_name, PC() + 1);
gen_rc(I_PUSH_EFFECTIVE_ADDRESS, explicit_ref_0,
"subprog. template");
gen(I_CREATE_STRUC);
gen_s(I_UPDATE_AND_DISCARD, proc_name);
}
} /* PREDEF */
}
/* Procedure elaboration */
void gen_subprogram(Node proc_node) /*;gen_subprogram*/
{
/*
* To generate code there are several delicate steps to perform, as
* the output of that is not only the proper code to elaborate the
* subprogram (which may even be reduced to nothing), but to produce
* a new code statement, adding some information to the previous
* code generation environment, and preserving the previous
* environment by "burying" it in local variables.
*
* Here is a summary of the steps for this procedure:
*
* 1) Assign a code slot number to the new procedure/function.
* Note: if the corresponding subprogram spec has been compiled, the
* code slot is already defined.
*
* 2) The relay set must be build. The current relay set is preserved,
* and a variable is put into the relay set when it cannot be found
* neither in the global nor the local reference map.
*
* 3) Compute offsets for the parameters, including offset for the
* types of arrays, and for the value returned by a function.
* The parameters are located below the stack frame pointer, but
* room shall be left for the return informations
*
* 4) After preserving the previous environment, generate code for
* the procedure/function in a new clean segment, starting with
* the "catch-all" exception handler.
*
* 5) generate code to elaborate the procedure/function (if not
* static)
*
* 6) restore previous environment
*/
Node decl_node, stmt_node, handler_node;
Symbol proc_name, fname, ftype, t_name, temp_name, name;
int tag, fmode, save_current_code_segment;
int simple_recursive_proc, has_separate_spec;
int const_addr_size, parameter_offset;
unsigned int location; /*OFFSET */
Fortup ft1;
int proc_code_segment, patch_addr;
Tuple save_local_reference_map, save_relay_set, save_subprog_specs;
unsigned int save_last_offset, save_max_offset;
Tuple save_parameter_set, save_code_patch_set, save_data_patch_set;
Tuple temp_relay_set, relay_table;
Segment tseg, save_code_segment;
unsigned int roff;
int i, dn, rn;
struct tt_subprog *tptr;
const_addr_size = mu_size(mu_addr);
gen(I_END); /* purge peep-hole buffer */
/*
*-----
* 1.
*/
stmt_node = N_AST1(proc_node);
decl_node = N_AST2(proc_node);
proc_name = N_UNQ(proc_node);
handler_node = N_AST4(proc_node);
tag = NATURE(proc_name);
#ifdef TRACE
if (debug_flag)
gen_trace_symbol("GEN_SUBPROGRAM", proc_name);
#endif
/*
*-----
* 2.
*/
save_relay_set = RELAY_SET;
save_local_reference_map = LOCAL_REFERENCE_MAP;
save_subprog_specs = SUBPROG_SPECS;
save_last_offset = LAST_OFFSET;
save_max_offset = MAX_OFFSET;
save_parameter_set = PARAMETER_SET;
save_code_patch_set = CODE_PATCH_SET;
save_data_patch_set = DATA_PATCH_SET;
save_code_segment = CODE_SEGMENT;
save_current_code_segment= CURRENT_CODE_SEGMENT;
RELAY_SET = tup_new(0);
LOCAL_REFERENCE_MAP = tup_new(0);
SUBPROG_SPECS = tup_new(0);
LAST_OFFSET = -SFP_SIZE;
MAX_OFFSET = 0;
PARAMETER_SET = tup_new(0);
CODE_PATCH_SET = tup_new(0);
DATA_PATCH_SET = tup_new(0);
CODE_SEGMENT = segment_new(SEGMENT_KIND_CODE, 0);
if (is_defined(proc_name)) { /* exists separate subprog spec */
CURRENT_CODE_SEGMENT = select_entry(SELECT_CODE, proc_name,
SLOTS_CODE_BORROWED);
}
else {
CURRENT_CODE_SEGMENT = select_entry(SELECT_CODE, proc_name, SLOTS_CODE);
}
parameter_offset = -const_addr_size;
FORTUP(fname = (Symbol), SIGNATURE(proc_name), ft1);
fmode = NATURE(fname);
ftype = TYPE_OF(fname);
if (!tup_mem((char *)fname, PARAMETER_SET)) {
PARAMETER_SET = tup_with(PARAMETER_SET, (char *) fname);
}
if (is_array_type(ftype)) {
/* Array addresses are mu_dble */
/*t_name= fname+'_type'; $ associate name*/
t_name= new_unique_name("fname_type");
assoc_symbol_put(fname, FORMAL_TEMPLATE, t_name);
local_reference_map_put(t_name, parameter_offset);
parameter_offset -= const_addr_size;
if (!tup_mem((char *) t_name, PARAMETER_SET)) {
PARAMETER_SET = tup_with(PARAMETER_SET, (char *) t_name);
}
}
local_reference_map_put(fname, (int) parameter_offset);
parameter_offset -= const_addr_size;
if ((is_simple_type(ftype) && (fmode != na_in))) {
/* scalar out and in out parameters takes 2 stacks locations */
/* one for returned na_out value, the other for temporary na_in */
parameter_offset -= const_addr_size;
}
ENDFORTUP(ft1);
if (tag == na_function ||
tag == na_function_spec ) { /* temporary kludge */
parameter_offset = parameter_offset + const_addr_size
- mu_size(kind_of(TYPE_OF(proc_name)));
t_name = new_unique_name("return_temp");
/* associated name */
assoc_symbol_put(proc_name, RETURN_TEMPLATE, t_name);
generate_object(t_name);
if (!tup_mem((char *)t_name, PARAMETER_SET)) {
PARAMETER_SET = tup_with(PARAMETER_SET, (char *) t_name);
}
local_reference_map_put(t_name, (int) parameter_offset);
}
#ifdef MACHINE_CODE
if (list_code) {
#ifdef TBSN
f_nam